import Request from 'luch-request';
import store from '@/store'
import authUtil from '@/util/authUtil.js'
import expireStorage from '@/util/storeUtil.js'

// 全局请求封装
var base_url = ''

// // #ifdef APP-PLUS
// base_url = 'http://106.75.37.116:8090/' 
// // #endif

//// #ifdef H5  || MP-ALIPAY || MP-WEIXIN
if (process.env.NODE_ENV === 'development') {
	base_url = '/proxyApi'
} else {
	base_url = 'http://192.168.142.157:8090/'
	// base_url = 'http://106.75.37.116:8090/'
}
////#endif


// 请求唯一id
var uniqueID = authUtil.generateUniqueId()
// 是否正在刷新token的标记
let isRefreshing = false
// 重试请求队列
let requestQueue = []

 
// 创建一个请求实例  
const http = new Request({
	baseURL: base_url,
	timeout: 20000,
	header: {
		'Content-Type': 'application/json;charset=UTF-8',
	},
});
 
// Loading全局实例  
let loadingInstance = null;
 
// 显示loading  
function showLoading(message = '加载中') {
	if (!loadingInstance) {
		loadingInstance = uni.showLoading({
			title: message,
			mask: true,
		});
	}
}
 
 
 
// 请求拦截器  
http.interceptors.request.use(
	(config) => {
		
		// 初始化请求拦截器时，会执行此方法，此时data为undefined，赋予默认{}
		config.data = config.data || {}
		// 根据custom参数中配置的是否需要token，添加对应的请求头
		if (config.custom.auth) {
			// 获取本地token
			const token = expireStorage.getCache('accessToken')
			// 请求头添加token
			if (token && token.length > 0 && token !== 'undefined') {
				config.header.Authorization = token
			}
		}
		config.header['X-Request-Id'] = uniqueID
		
		// 显示loading（可根据需要添加条件）  
		showLoading();
		return config;
	},
	(error) => {
		return Promise.reject(error);
	}
);
 
// 响应拦截器  
http.interceptors.response.use(
		(response) => {
			// /* 对响应成功做点什么 可使用async await 做异步操作*/
			// const data = response.data
			// if (!data || data.code !== '000000'){
			//   // 自定义参数
			//   const custom = response.config.custom
			//   // 如果没有显式定义custom的toast参数为false的话，默认对报错进行toast弹出提示
			//   if (custom.toast) uni.$u.toast(data.message || '请求超时或服务器异常')
			//   // 如果需要catch返回，则进行reject
			//   if (custom.catch) return Promise.reject(data)
			//   else return new Promise(() => {}) // 否则返回一个pending中的promise，请求不会进入catch中
			// }
			// 隐藏loading
			uni.hideLoading()
			return response;
		},
		async (error) => {
			// 隐藏loading（确保无论成功还是失败都隐藏loading）
			uni.hideLoading()
			if (error.statusCode == 401) {
				if (needRefresh(error.data)) {
					if (!isRefreshing) {
						// 正在刷新
						isRefreshing = true
						store.dispatch('RefreshToken').then(({
							data
						}) => {
							isRefreshing = false;
							store.commit("SET_ACCESS_TOKEN", data.data.accessToken);
							requestQueue.forEach(async ({
								fn,
								resolve
							}) => {
								// 逐个按请求队列顺序重新发起请求
								const res = await fn()
								resolve(res)
							})
							requestQueue = [] // 清空请求队列
							// 再发请求
							let token = data.data.accessToken
							error.config.headers.Authorization = token
							return uni.$u.http.request(error.config);
						}).catch((err) => {
							isRefreshing = false;
						})
					} else {
						// 同时并发出现的请求 新的token没回来之前 先用promise 存入等待队列中
						return new Promise((resolve) => {
							const fn = () => Promise.resolve(uni.$u.http.request(error.config))
							requestQueue.push({
								fn,
								resolve
							})
						})
					}
				} else {
					// 移除token
					expireStorage.removeCache('accessToken')
					expireStorage.removeCache('refreshToken')
					return uni.$u.toast('请登录')
				}
			}
			return error;
		}
);
 


/**
 * 是否需要刷新token
 * @param res
 * @returns {*|boolean}
 */
function needRefresh(data) {
	const token = expireStorage.getCache('accessToken')
	if (!token || token.length < 1 || token == 'undefined') {
		return false
	}
	return data && data.code && (data.code == '200002' || data.code == '200000');
}

/**
 * 获取服务端url
 */
export function getBaseUrl() {
	return base_url;
}


/**
 * GET请求
 */
export function get(url,data,custom){
	return request({
			url: url,
			method: 'GET',
			data: {
				...data,
			},
			custom: {
				auth: true,
				showLoading: false,
				...custom,
			},
		})
}


/**
 * POST请求
 */
export function post(url,data,custom){
	return request({
			url: url,
			method: 'POST',
			data: {
				...data,
			},
			custom: {
				auth: true,
				showLoading: false,
				...custom,
			},
		})
}


/**
 * PUT请求
 */
export function put(url,data,custom){
	return request({
			url: url,
			method: 'PUT',
			data: {
				...data,
			},
			custom: {
				auth: true,
				showLoading: false,
				...custom,
			},
		})
}


/**
 * DELETE请求
 */
export function delete(url,data,custom){
	return request({
			url: url,
			method: 'DELETE',
			data: {
				...data,
			},
			custom: {
				auth: true,
				showLoading: false,
				...custom,
			},
		})
}